package com.istock.monitor.agent.transformer;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AspectJCreatorClassWriter implements ClassRewriter, Opcodes {

	@Override
	public boolean canRewriter(String className) {
		return "org/springframework/aop/aspectj/autoproxy/AspectJAwareAdvisorAutoProxyCreator".equals(className);
	}
	@Override
	public byte[] rewriteClass(byte[] classFileByte) {
		System.out.println("=============ready to rewrite AspectjCreator==============");
		ClassReader cr = new ClassReader(classFileByte);
		ClassWriter cw = new ClassWriter(cr,ClassWriter.COMPUTE_FRAMES);
		cr.accept(new AspectJCreatorClassAdapter(ASM5 , cw), ClassReader.SKIP_DEBUG);
		return cw.toByteArray();
	}

	class AspectJCreatorClassAdapter extends ClassVisitor{

		public AspectJCreatorClassAdapter(int api, ClassVisitor cv) {
			super(api, cv);
		}

		@Override
		public MethodVisitor visitMethod(int access, String name, String desc,
				String signature, String[] exceptions) {
			MethodVisitor mvb = super.visitMethod(access, name, desc, signature, exceptions);
			if (name.equals("shouldSkip") && desc.equals("(Ljava/lang/Class;Ljava/lang/String;)Z")) {
				mvb =  new AspectJCreatorMethodVisitor(ASM5 , mvb);
			}
			return mvb;
		}
	}
	
	class AspectJCreatorMethodVisitor extends MethodVisitor{

		public AspectJCreatorMethodVisitor(int api, MethodVisitor mv) {
			super(api, mv);
		}
		public AspectJCreatorMethodVisitor(int api) {
			super(api);
		}

		@Override
		public void visitCode() {
			mv.visitCode();
			Label l0 = new Label();
			mv.visitLabel(l0);
			mv.visitLineNumber(35, l0);
			mv.visitVarInsn(ALOAD, 0);
			mv.visitVarInsn(ALOAD, 1);
			mv.visitMethodInsn(INVOKESPECIAL, "com/istock/monitor/agent/util/ClassUtils", "canProxy", "(Ljava/lang/Class;)Z", false);
			Label l1 = new Label();
			mv.visitJumpInsn(IFEQ, l1);
		}

		@Override
		public void visitInsn(int opcode) {
//			mv.visitInsn(opcode);
		}
	}
}
